package com.wnxy.e_reentrant;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 通过可重入锁解决线程安全问题。超卖问题。
 */
public class TicketDemo2 {
    // 总票数
    private static int ticket = 50;

    public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();

        Runnable runnable = ()-> {
            while (true) {
                // 这里休眠一下，就能模拟出超卖现象
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    // 【获取锁】
                    //lock.lock();
                    // 【获取锁；指定等待3秒，如果等待3秒还是没有获取到锁，返回false；避免一直等待】
                    boolean flag = lock.tryLock(3, TimeUnit.SECONDS);
                    if (flag) {
                        if (ticket > 0) {
                            ticket--;
                            System.out.println(Thread.currentThread().getName() +
                                    "卖了一张票，剩余：" + ticket);
                        } else {
                            // 票已卖完
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 【释放锁】
                    lock.unlock();
                }
            }
        };

        // 模拟三个售票窗口, 用三个线程表示
        Thread t1 = new Thread(runnable,"售票窗口1");
        Thread t2 = new Thread(runnable,"售票窗口2");
        Thread t3 = new Thread(runnable,"售票窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}
